package com.kitty.game.activity.service.time;

import com.kitty.common.utils.SpringUtils;
import com.kitty.common.utils.ConcurrentHashSet;
import com.kitty.common.core.SchedulerManager;
import com.kitty.game.ServerService;
import com.kitty.game.activity.model.product.ActivityType;

import com.kitty.game.boss.config.BossSet;
import com.kitty.game.boss.model.BossFightParam;
import com.kitty.game.boss.model.BossParam;
import com.kitty.game.boss.service.NewBossService;
import com.kitty.game.config.GameMap;
import com.kitty.game.config.NPC;
import com.kitty.game.config.Xing;
import com.kitty.game.enter.Position;
import com.kitty.game.equip.message.RespNotifyMiscEx;
import com.kitty.game.equip.service.SuitService;
import com.kitty.game.fight.bean.Fight;
import com.kitty.game.fight.service.FightService;
import com.kitty.game.map.service.MapService;
import com.kitty.game.npc.model.NpcButton;
import com.kitty.game.role.model.Role;
import com.kitty.game.team.model.Team;
import com.kitty.game.utils.Const;
import com.kitty.game.utils.TimeUtil;
import com.kitty.listener.event.FightEndEvent;
import com.kitty.mina.cache.DataCache;
import com.kitty.mina.message.MessagePusher;
import org.nutz.dao.Cnd;
import org.nutz.dao.Dao;
import org.nutz.lang.util.NutMap;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.text.MessageFormat;
import java.util.*;
import java.util.concurrent.ThreadLocalRandom;



/**
 * 天地星处理类 36天罡星、72地煞星
 */
@Component
public class XingGuanHandler extends FightActivityHandler {
    @Autowired
    FightService fightService;
    /**
     * 各职业对应等级武器和技能数据
     */
    public static NutMap data = new NutMap();
    /**
     * 星官ID对应将要出现的mapId, key: 星官id, value: 地图id
     */
    private static Map<Integer, Integer> xingGuanMapId = new HashMap<>();
    /**
     * 性别列表
     */
    private static final List<Byte> SEX_LIST = Arrays.asList(Const.SEX_MALE, Const.SEX_FEMALE);
    /**
     * 相性列表
     */
    private static final List<Short> XIANG_XIN_LIST = Arrays.asList((short) 1, (short) 2, (short) 3, (short) 4, (short) 5);
    /**
     * 发光xx ID列表
     */
    private static final List<Integer> FAGUANG_ID_LIST = Arrays.asList(7001, 7002, 7003, 7004, 7005);

    /**
     * 星官在服务启动后多久开始刷新
     */
    private static final int XINGGUAN_FLUSH_DELAY_AFTER_SERVER_START = (int) (0 * TimeUtil.ONE_MINUTE);//原先是1分钟以后在刷星 不知道为什么要等一分钟
    /**
     * 星官之间刷新最小间隔秒数
     */
    private static final int XINGGUAN_FLUSH_INTERVAL_SEC = 1;
    /**
     * 星官提前播报分钟数
     */
    private static final int XINGGUAN_PREPARE_MINUTE = 1;
    /**
     * 星官显示的分钟数
     */
    private static final int XINGGUAN_SHOW_MINUTE = 15;
    /**
     * 星官被打败后后刷新等待分钟数
     */
    private static final int XINGGUAN_NEXT_SHOW = 10;
    /**
     * 最少组队人数
     */
    private static final int MIN_TEAM_COUNT = 1;
    /**
     * 星官在前3分钟只能由星官随机的玩家挑战
     */
    private static final int XINGGUAN_RANDOM_ROLE_FIGHT_TIME = (int) (3 * TimeUtil.ONE_MINUTE);
    /**
     * 奖励最大超过等级
     */
    private static final int REWARD_MAX_MORE_LEVEL = 29;

    /**
     * 星官3分钟后要出现的谣言内容
     */
    private static final String XINGGUAN_WILL_COME_NUMOR = "听闻在#R{0}#n，#Y{1}#n#R（{2}级）#n将在#R三分钟后#n下凡云游到#Z{3}#Z，期间星君将挑选幸运的道友进行指点，各位道友快去该地图等候吧！";
    private static final String XINGGUAN_COME_NUMOR = "#Y{0}#n#R（{1}级）#n已经出现在#R{2}#n#Z{3}#Z，各位道友可前往挑战！超过#R10#n分钟，#Y{0}#n#R（{1}级）#n将会消失！若星君被击败也将离去，各位道友可千万别错过！";
    private static final String CONTENT = "我乃天界星官{0}（{1}级），巡游至此，你一介凡人，怎可挡我去路？#R高于星官29级以上将无法获得奖励。#n#R战斗结束时死亡的角色会受到惩罚。#n[我是来向你挑战的/" + NpcButton.FIGHT_TO_XING_GUAN.getKey() + "][我是路过的/离开]";
    private static final String IN_FIGHT = "道友来的不是时候，小仙此时正在指点其他道友。[离开]";
    private static final String TEAM_COUNT_NOT_ENOUGH = "试炼之路独行乃大忌，还是凑齐#R{0}#n人再来挑战我吧。#n[离开]";
    private static final String REMAIN_COUNT_NOT_ENOUGH = "#Y{0}#n本日击杀天罡地煞星剩余次数已经用完。[离开]";
    private static final String NOT_YOU = "当前没有挑战资格，请耐心等待3分钟后即可挑战。[离开]";
    private static final String SELECTED_TIPS = "恭喜你，被#R星官{0}（{1}级）#n选中，请速与之前来挑战。";
    private static final String SELECTED_TEAM_TIPS = "恭喜，你当前队伍的#Y{0}#n已被#R星官{1}（{2}级）#n选中，请速与之前来挑战。";
    private static final String MAIL_TITLE = "挑战{0}";
    private static final String MAIL_CONTENT = "#R恭喜#n#Y{0}#n，我乃#R{1}（{2}级）#n。遵天命，今特邀你在#R{3}#n处挑战。我只等你3分钟，请速不挑战。如果你挑战成功，将会获得丰厚的奖励。";


    /**
     * 初始化各职业对应等级武器和技能数据
     */
    @PostConstruct
    private void initData() {
        data.setv("1", NutMap.NEW());
        data.getAs("1", NutMap.class).setv("30", 1137).setv("300", "2,501,11,21,32");
        data.getAs("1", NutMap.class).setv("40", 1138).setv("400", "2,501,11,12,21,22,32,33");
        data.getAs("1", NutMap.class).setv("50", 1139).setv("500", "2,501,11,12,13,21,22,23,32,33,34");
        data.getAs("1", NutMap.class).setv("60", 1140).setv("600", "2,501,11,12,13,14,32,33,34");
        data.getAs("1", NutMap.class).setv("70", 1141).setv("700", "2,501,11,12,13,14,32,33,34");
        data.getAs("1", NutMap.class).setv("80", 1142).setv("800", "2,501,11,12,13,14,32,33,34");
        data.getAs("1", NutMap.class).setv("90", 1143).setv("900", "2,501,11,12,13,14,32,33,34");
        data.getAs("1", NutMap.class).setv("100", 1162).setv("1000", "2,501,11,12,13,14,15,22,23,24,25,21,32,33,34,35");
        data.getAs("1", NutMap.class).setv("110", 1163).setv("1100", "2,501,11,12,13,14,15,22,23,24,25,21,32,33,34,35");
        data.getAs("1", NutMap.class).setv("120", 1144).setv("1200", "2,501,11,12,13,14,15,22,23,24,25,21,32,33,34,35");
        data.getAs("1", NutMap.class).setv("130", 1168).setv("1300", "2,501,11,12,13,14,15,22,23,24,25,21,32,33,34,35");
        data.getAs("1", NutMap.class).setv("140", 1171).setv("1400", "2,501,11,12,13,14,15,22,23,24,25,21,32,33,34,35");
        data.getAs("1", NutMap.class).setv("150", 1176).setv("1500", "2,501,11,12,13,14,15,22,23,24,25,21,32,33,34,35");
        data.getAs("1", NutMap.class).setv("160", 1181).setv("1600", "2,501,11,12,13,14,15,22,23,24,25,21,32,33,34,35");
        data.getAs("1", NutMap.class).setv("170", 3001).setv("1700", "2,501,11,12,13,14,15,22,23,24,25,21,32,33,34,35");

        data.setv("2", NutMap.NEW());
        data.getAs("2", NutMap.class).setv("30", 1148).setv("300", "2,501,61,71,81");
        data.getAs("2", NutMap.class).setv("40", 1149).setv("400", "2,501,61,62,71,72,81,82");
        data.getAs("2", NutMap.class).setv("50", 1150).setv("500", "2,501,61,62,63,71,72,73,81,82,83");
        data.getAs("2", NutMap.class).setv("60", 1151).setv("600", "2,501,61,62,63,64,81,82,83,84");
        data.getAs("2", NutMap.class).setv("70", 1152).setv("700", "2,501,61,62,63,64,81,82,83,84");
        data.getAs("2", NutMap.class).setv("80", 1153).setv("800", "2,501,61,62,63,64,81,82,83,84");
        data.getAs("2", NutMap.class).setv("90", 1154).setv("900", "2,501,61,62,63,64,81,82,83,84");
        data.getAs("2", NutMap.class).setv("100", 1155).setv("1000", "2,501,61,62,63,64,65,71,72,73,74,75,81,82,83,84,85");
        data.getAs("2", NutMap.class).setv("110", 1165).setv("1100", "2,501,61,62,63,64,65,71,72,73,74,75,81,82,83,84,85");
        data.getAs("2", NutMap.class).setv("120", 1164).setv("1200", "2,501,61,62,63,64,65,71,72,73,74,75,81,82,83,84,85");
        data.getAs("2", NutMap.class).setv("130", 1166).setv("1300", "2,501,61,62,63,64,65,71,72,73,74,75,81,82,83,84,85");
        data.getAs("2", NutMap.class).setv("140", 1172).setv("1400", "2,501,61,62,63,64,65,71,72,73,74,75,81,82,83,84,85");
        data.getAs("2", NutMap.class).setv("150", 1177).setv("1500", "2,501,61,62,63,64,65,71,72,73,74,75,81,82,83,84,85");
        data.getAs("2", NutMap.class).setv("160", 1182).setv("1600", "2,501,61,62,63,64,65,71,72,73,74,75,81,82,83,84,85");
        data.getAs("2", NutMap.class).setv("170", 3002).setv("1700", "2,501,61,62,63,64,65,71,72,73,74,75,81,82,83,84,85");

        data.setv("3", NutMap.NEW());
        data.getAs("3", NutMap.class).setv("30", 1126).setv("300", "2,501,110,121,131");
        data.getAs("3", NutMap.class).setv("40", 1127).setv("400", "2,501,110,111,121,122,131,132");
        data.getAs("3", NutMap.class).setv("50", 1128).setv("500", "2,501,110,111,112,121,122,123,131,132,133");
        data.getAs("3", NutMap.class).setv("60", 1129).setv("600", "2,501,110,111,112,113,131,132,133,134");
        data.getAs("3", NutMap.class).setv("70", 1130).setv("700", "2,501,110,111,112,113,131,132,133,134");
        data.getAs("3", NutMap.class).setv("80", 1131).setv("800", "2,501,110,111,112,113,131,132,133,134");
        data.getAs("3", NutMap.class).setv("90", 1132).setv("900", "2,501,110,111,112,113,131,132,133,134");
        data.getAs("3", NutMap.class).setv("100", 1133).setv("1000", "2,501,110,111,112,113,114,135,131,132,133,134");
        data.getAs("3", NutMap.class).setv("110", 1160).setv("1100", "2,501,110,111,112,113,114,135,131,132,133,134");
        data.getAs("3", NutMap.class).setv("120", 1161).setv("1200", "2,501,110,111,112,113,114,135,131,132,133,134");
        data.getAs("3", NutMap.class).setv("130", 1169).setv("1300", "2,501,110,111,112,113,114,135,131,132,133,134");
        data.getAs("3", NutMap.class).setv("140", 1173).setv("1400", "2,501,110,111,112,113,114,135,131,132,133,134");
        data.getAs("3", NutMap.class).setv("150", 1178).setv("1500", "2,501,110,111,112,113,114,135,131,132,133,134");
        data.getAs("3", NutMap.class).setv("160", 1183).setv("1600", "2,501,110,111,112,113,114,135,131,132,133,134");
        data.getAs("3", NutMap.class).setv("170", 3003).setv("1700", "2,501,110,111,112,113,114,135,131,132,133,134");

        data.setv("4", NutMap.NEW());
        data.getAs("4", NutMap.class).setv("30", 1104).setv("300", "2,501,161,171,181");
        data.getAs("4", NutMap.class).setv("40", 1105).setv("400", "2,501,161,162,171,172,181,182");
        data.getAs("4", NutMap.class).setv("50", 1106).setv("500", "2,501,161,162,163,171,172,173,181,182,183");
        data.getAs("4", NutMap.class).setv("60", 1107).setv("600", "2,501,161,162,163,164,184,181,182,183");
        data.getAs("4", NutMap.class).setv("70", 1108).setv("700", "2,501,161,162,163,164,184,181,182,183");
        data.getAs("4", NutMap.class).setv("80", 1109).setv("800", "2,501,161,162,163,164,184,181,182,183");
        data.getAs("4", NutMap.class).setv("90", 1110).setv("900", "2,501,161,162,163,164,184,181,182,183");
        data.getAs("4", NutMap.class).setv("100", 1157).setv("1000", "2,501,161,165,175,185,162,163,164,174,184,171,172,173,181,182,183");
        data.getAs("4", NutMap.class).setv("110", 1111).setv("1100", "2,501,161,165,175,185,162,163,164,174,184,171,172,173,181,182,183");
        data.getAs("4", NutMap.class).setv("120", 1156).setv("1200", "2,501,161,165,175,185,162,163,164,174,184,171,172,173,181,182,183");
        data.getAs("4", NutMap.class).setv("130", 1167).setv("1300", "2,501,161,165,175,185,162,163,164,174,184,171,172,173,181,182,183");
        data.getAs("4", NutMap.class).setv("140", 1174).setv("1400", "2,501,161,165,175,185,162,163,164,174,184,171,172,173,181,182,183");
        data.getAs("4", NutMap.class).setv("150", 1179).setv("1500", "2,501,161,165,175,185,162,163,164,174,184,171,172,173,181,182,183");
        data.getAs("4", NutMap.class).setv("160", 1184).setv("1600", "2,501,161,165,175,185,162,163,164,174,184,171,172,173,181,182,183");
        data.getAs("4", NutMap.class).setv("170", 3004).setv("1700", "2,501,161,165,175,185,162,163,164,174,184,171,172,173,181,182,183");

        data.setv("5", NutMap.NEW());
        data.getAs("5", NutMap.class).setv("30", 1115).setv("300", "2,501,210,221,231");
        data.getAs("5", NutMap.class).setv("40", 1116).setv("400", "2,501,210,211,221,222,231,232");
        data.getAs("5", NutMap.class).setv("50", 1117).setv("500", "2,501,210,211,212,232,233");
        data.getAs("5", NutMap.class).setv("60", 1118).setv("600", "2,501,210,213,234,211,212,231,232,233");
        data.getAs("5", NutMap.class).setv("70", 1119).setv("700", "2,501,210,213,234,211,212,231,232,233");
        data.getAs("5", NutMap.class).setv("80", 1120).setv("800", "2,501,210,213,234,211,212,231,232,233");
        data.getAs("5", NutMap.class).setv("90", 1121).setv("900", "2,501,210,213,234,211,212,231,232,233");
        data.getAs("5", NutMap.class).setv("100", 1122).setv("1000", "2,501,210,213,214,235,225,224,234,211,212,221,222,223,231,232,233");
        data.getAs("5", NutMap.class).setv("110", 1158).setv("1100", "2,501,210,213,214,235,225,224,234,211,212,221,222,223,231,232,233");
        data.getAs("5", NutMap.class).setv("120", 1159).setv("1200", "2,501,210,213,214,235,225,224,234,211,212,221,222,223,231,232,233");
        data.getAs("5", NutMap.class).setv("130", 1170).setv("1300", "2,501,210,213,214,235,225,224,234,211,212,221,222,223,231,232,233");
        data.getAs("5", NutMap.class).setv("140", 1175).setv("1400", "2,501,210,213,214,235,225,224,234,211,212,221,222,223,231,232,233");
        data.getAs("5", NutMap.class).setv("150", 1180).setv("1500", "2,501,210,213,214,235,225,224,234,211,212,221,222,223,231,232,233");
        data.getAs("5", NutMap.class).setv("160", 1185).setv("1600", "2,501,210,213,214,235,225,224,234,211,212,221,222,223,231,232,233");
        data.getAs("5", NutMap.class).setv("170", 3005).setv("1700", "2,501,210,213,214,235,225,224,234,211,212,221,222,223,231,232,233");
    }

    /**
     * 加载星官配置
     */
    public void loadXingGuanSet() {
        Dao dao = SpringUtils.getBean(Dao.class);
        List<Xing> list = dao.query(Xing.class, Cnd.NEW());
        for (Xing xing : list) {
            if (xing.getLevel() >=100){
                int rate = 2;
                xing.setQixue(xing.getQixue()*rate);
                xing.setFagong(xing.getFagong()*rate);
                xing.setWugong(xing.getWugong()*rate);
                xing.setFangyu(xing.getFangyu()*rate);
                xing.setDaohang(xing.getDaohang()*rate);
                xing.setRewardDaohang(xing.getRewardDaohang()*2);
            }
            if (xing.getLevel() >=110){
                int rate = 2;
                xing.setQixue(xing.getQixue()*rate);
                xing.setFagong(xing.getFagong()*rate);
                xing.setWugong(xing.getWugong()*rate);
                xing.setFangyu(xing.getFangyu()*rate);
                xing.setDaohang(xing.getDaohang()*rate);
                xing.setRewardDaohang(xing.getRewardDaohang()*2);
            }
            if (xing.getLevel() >=124){
                int rate = 2;
                xing.setQixue(xing.getQixue()*rate);
                xing.setFagong(xing.getFagong()*rate);
                xing.setWugong(xing.getWugong()*rate);
                xing.setFangyu(xing.getFangyu()*rate);
                xing.setDaohang(xing.getDaohang()*rate);
                xing.setRewardDaohang(xing.getRewardDaohang()*2);
            }
            if (xing.getLevel() >=125){
                int rate = 2;
                xing.setWugong(xing.getWugong()*rate);
                xing.setFagong(xing.getFangyu()*rate);
            }
            if("1".equals(xing.getXingtype())){
                xing.setWugong(xing.getWugong()*2);
                xing.setFagong(xing.getFangyu()*2);
                DataCache.BIANYIXING_SET.put(xing.getLevel(), xing);
            }else{
                DataCache.XING_SET.put(xing.getId(), xing);
            }

        }
    }

    /**
     * 服务启动后刷新所有星官
     */
    public void flushXingGuanAfterServerStart() {
        if (SpringUtils.getBean(ServerService.class).getServer().getId() == 10000){
            return;
        }
        int delay = XINGGUAN_FLUSH_DELAY_AFTER_SERVER_START;
        for (Xing xingGuan : DataCache.XING_SET.values()) {
            if (xingGuan.getLevel() < 60){
                continue;
            }
            /**每个星官刷新间隔开*/
            delay += XINGGUAN_FLUSH_INTERVAL_SEC * 200;
            SchedulerManager.getInstance().schedule(() -> xingGuanWillCome(xingGuan), delay);
        }
    }


    /**
     * 星官出现前3分钟发谣言
     */
    private void xingGuanWillCome(Xing xingGuan) {
        String serverName = SpringUtils.getBean(ServerService.class).getServer().getSonName();
        GameMap map = randomMap(xingGuan);

        /**发谣言*/
        String msg = MessageFormat.format(XINGGUAN_WILL_COME_NUMOR, serverName, xingGuan.getName(), xingGuan.getLevel(), map.getName());
        SpringUtils.getChatService().sendNumor(msg, Const.BRODCAST_MSG_TYPE_ROLE);

        /**定时任务在3分钟后出现*/
        SchedulerManager.getInstance().schedule(() -> xingGuanHasCome(xingGuan), XINGGUAN_PREPARE_MINUTE * TimeUtil.ONE_MINUTE);
//        logger.error("星官的等级=={}=={}",xingGuan.getName(),xingGuan.getLevel());
    }

    /**
     * 随机星官出现所在地图
     */
    private GameMap randomMap(Xing xingGuan) {
        int index = ThreadLocalRandom.current().nextInt(xingGuan.getBornMap().size());
        String mapName = xingGuan.getBornMap().get(index);
        MapService mapService = SpringUtils.getMapService();
        int mapId = mapService.getMapIdByName(mapName);
        xingGuanMapId.put(xingGuan.getId(), mapId);
        return mapService.getMap(mapId);
    }


    /**
     * 星官已经到来
     */
    private void xingGuanHasCome(Xing xingGuan) {
        NPC npc = createXingGuan(xingGuan);

        /**发谣言*/
        String serverName = SpringUtils.getBean(ServerService.class).getServer().getSonName();
        GameMap map = SpringUtils.getMapService().getMap(npc.getMapId());
        String msg = MessageFormat.format(XINGGUAN_COME_NUMOR, xingGuan.getName(), xingGuan.getLevel(), serverName, map.getName());
        SpringUtils.getChatService().sendNumor(msg, Const.BRODCAST_MSG_TYPE_ROLE);

        /**定时任务在持续时间完成后移除*/
        SchedulerManager.getInstance().schedule(() -> clearXingGuanTimeOut(npc), XINGGUAN_SHOW_MINUTE * TimeUtil.ONE_MINUTE);
    }

    /**
     * 星官刷新到地图
     */
    private NPC createXingGuan(Xing xingGuan) {
        if (xingGuan == null) {
            return null;
        }
        Integer mapId = xingGuanMapId.get(xingGuan.getId());
        /**没有要出现的地图ID时 返回*/
        if (mapId == null) {
            return null;
        }

        Position position = getRandomPosition(mapId);
        NPC npc = new NPC();
        npc.setId(SpringUtils.getBean(NewBossService.class).getTempNpcId());
        npc.setX(position.getX());
        npc.setY(position.getY());
        npc.setFangxiang((short) new Random().nextInt(8));
        npc.setMapId(mapId);
        npc.setCreateTime(System.currentTimeMillis());
        npc.setEndTime(npc.getCreateTime() + XINGGUAN_SHOW_MINUTE * TimeUtil.ONE_MINUTE);
        npc.setType(NPC.TYPE_XING_GUAN);
        //npc.setContent(CONTENT);
        npc.setName(xingGuan.getName());
        npc.setLevel(xingGuan.getLevel());
        npc.setXing(xingGuan);

        byte sex = getRandomSex();
        short polar = getRandomXiangXin();
        int level = getLevel(xingGuan.getLevel());

        int weaponId = data.getAs(String.valueOf(polar), NutMap.class).getInt(String.valueOf(level));
        npc.setWuqiId(weaponId);
        npc.setIcon(SpringUtils.getMapService().heroIcon(sex, polar));
        int suitId = SpringUtils.getBean(SuitService.class).getSuitId(level, sex, polar);
        npc.setTaozhuangId(suitId);
        if (level >= 70) {
            int lightId = getRandomLightId();
            npc.setFaguangId(lightId);
        }
        npc.setRoleUid(getRandomRole(mapId));

        DataCache.XING_NPCS.put(npc.getId(), npc);
        Set<Integer> set = DataCache.XING_MAP_NPC.computeIfAbsent(mapId, k -> new HashSet<>());
        set.add(npc.getId());

        bossService.broadcastNpcShow(null, npc);

        if (npc.getRoleUid() > 0) {
            /**发资格邮件*/
             Role role = SpringUtils.getRoleService().getOnlinePlayer(npc.getRoleUid());
//            String title = MessageFormat.format(MAIL_TITLE, npc.getName());
//            MailService mailService = SpringUtils.getMailService();
//
//            GameMap map = SpringUtils.getMapService().getMap(mapId);
//            String content = MessageFormat.format(MAIL_CONTENT, role.getName(), npc.getName(), npc.getLevel(), map.getName());
//            Mail mail = mailService.createMail(title, content, TimeUtil.ONE_HOUR);
//            mailService.sendNewMail(role, mail);

            /**发资格提示*/
            String tips = null;
            if (teamService.isInTeam(role)) {
                tips = MessageFormat.format(SELECTED_TEAM_TIPS, role.getName(), npc.getName(), npc.getLevel());
            } else {
                tips = MessageFormat.format(SELECTED_TIPS, npc.getName(), npc.getLevel());
            }
            teamService.pushMessage(role, new RespNotifyMiscEx(tips));
        }

        return npc;
    }

    private short getRandomXiangXin() {
        int index = ThreadLocalRandom.current().nextInt(XIANG_XIN_LIST.size());
        return XIANG_XIN_LIST.get(index);
    }

    private byte getRandomSex() {
        int index = ThreadLocalRandom.current().nextInt(SEX_LIST.size());
        return SEX_LIST.get(index);
    }

    private int getLevel(int level) {
        return level - level % 10;
    }

    private int getRandomLightId() {
        int index = ThreadLocalRandom.current().nextInt(FAGUANG_ID_LIST.size());
        return FAGUANG_ID_LIST.get(index);
    }

    /**
     * 获得指定地图随机一个玩家
     */
    public long getRandomRole(int mapId) {
        ConcurrentHashSet<Integer> set = SpringUtils.getMapService().getRoleIds(null, mapId);
        if (set == null || set.size() <= 0) {
            return 0;
        }
        ArrayList<Integer> arrayList = new ArrayList(set);
        int index = ThreadLocalRandom.current().nextInt(arrayList.size());
        int roleId = arrayList.get(index);
        Role role = SpringUtils.getRoleService().getOnlinePlayer(roleId);
        return role != null ? role.getUid() : 0;
    }

    /**
     * 时间结束时移除星官，还在战斗时只让不显示
     */
    private void clearXingGuanTimeOut(NPC npc) {
        if (npc == null) {
            return;
        }
        /**已经被删除，返回*/
        if (DataCache.XING_NPCS.get(npc.getId()) == null) {
            return;
        }

        if (npc.isInFight()) {
            /**在战斗中隐藏*/
            bossService.broadcastNpcHide(null, npc);
        } else {
            /**否则直接删除*/
            clearXingGuan(npc);

            /**同时开始发谣言3分钟后星官出现*/
//            xingGuanWillCome(npc.getXing());
        }
    }

    /**
     * 获得与星官对话
     */
    public String getNpcContent(Role role, NPC bossNpc) {
        return MessageFormat.format(CONTENT, bossNpc.getName(), bossNpc.getLevel());
    }

    public String getNpcContentNotFight(Role role, NPC bossNpc) {
        /**检测是否在战斗中*/
        if (bossNpc.isInFight()) {
            return IN_FIGHT;
        }

        /**检测队伍人数*/
        int teamCount = teamService.getTeamCount(role);
        if (teamCount < MIN_TEAM_COUNT) {
            return MessageFormat.format(TEAM_COUNT_NOT_ENOUGH, MIN_TEAM_COUNT);
        }

        /**检测剩余次数*/
        Team team = teamService.getTeam(role.getRoleId());
        String names = null;
        if (bossNpc.getName().contains("天")){
            names = teamService.checkMember(team, memberRole -> !SpringUtils.getActivityService().isHaveRemainCount(memberRole, ActivityType.XING_GUAN_tian));
        }else {
            names = teamService.checkMember(team, memberRole -> !SpringUtils.getActivityService().isHaveRemainCount(memberRole, ActivityType.XING_GUAN_di));
        }
        if (names != null) {
            return MessageFormat.format(REMAIN_COUNT_NOT_ENOUGH, names);
        }

        /**如果有幸运儿时，前3分钟只能幸运儿挑战，之后的时间才能所有人挑战*/
        if (bossNpc.getRoleUid() != 0 && System.currentTimeMillis() - bossNpc.getCreateTime() < XINGGUAN_RANDOM_ROLE_FIGHT_TIME) {
            names = teamService.checkMember(team, memberRole -> memberRole.getUid() == bossNpc.getRoleUid());
            /**当前不是幸运儿时，返回*/
            if (names == null) {
                return NOT_YOU;
            }
        }

        return null;
    }

    public void doStartFight(Role role, NPC bossNpc) {
        List<BossParam> bossParamList = newBossParamList(role, bossNpc);
        BossFightParam bossFightParam = new BossFightParam(bossParamList, getFightType(bossNpc));
        bossFightParam.setNpcId(bossNpc.getId());
        bossFightParam.setNpcLevel((short) bossNpc.getXing().getLevel());
        bossFightParam.setReward(NutMap.NEW().setv("rewardLevel", bossNpc.getXing().getLevel()));
        Fight fight = bossService.startFightToBoss(role, bossFightParam);

        /*星官消耗积分*/
        /*if(null != fight) {
            int score = (int) (Math.random()*10);
            teamService.memberHandle(role, memberRole ->
                    {
                        SpringUtils.getRoleService().substractChargeScore(role, score);
                        MessagePusher.pushMessage(role,new RespNotifyMiscEx("战斗消耗#R"+score+"#n积分！"));
                        MessagePusher.notify2Player(memberRole, I18nId.PMT_1018);
                    }
            );
        }*/

    }
    protected int getFightType(NPC bossNpc) {
//        if (bossNpc.getName().contains("天")){
//            return Const.fightType_xing;
//        }else {
//            return Const.fightType_dixing;
//        }
        return Const.fightType_xing;
    }
    @Override
    protected int getFightType(Role role) {
        return Const.fightType_xing;
    }

    @Override
    protected NPC getBossNpc(int npcId) {
        return DataCache.XING_NPCS.get(npcId);
    }

    @Override
    protected void clearNpcAfterWin(Role role, NPC bossNpc) {
        clearXingGuanAfterFightWin(bossNpc);
    }

    private List<BossParam> newBossParamList(Role role, NPC bossNpc) {
        List<BossParam> bossParamList = new ArrayList<>();
        int count = 10;

        /**npc对应的加在第1个*/
        bossParamList.add(newBossParam(bossNpc));

        /**加count-1个*/
        for (int i = 1; i < count; i++) {
            bossParamList.add(newBossParam(bossNpc));
        }

        return bossParamList;
    }

    private BossParam newBossParam(NPC bossNpc) {
        BossSet bossSet = bossNpc.getXing();
        BossParam bossParam = new BossParam(bossSet, bossNpc.getName());

        /**相性*/
        short xiangXin = getRandomXiangXin();
        bossParam.setPolar(xiangXin);

        int level = getLevel(((Xing) bossSet).getLevel());
        byte sex = getRandomSex();

        /**技能ID列表*/
        String skillStr = data.getAs(String.valueOf(xiangXin), NutMap.class).getString(level + "0");
        String[] strings = skillStr.split(",");
        ArrayList<Integer> skillIds = new ArrayList<>();
        for (String s : strings) {
            skillIds.add(Integer.parseInt(s));
        }
        bossParam.setSkillIds(skillIds);

        /**icon*/
        short icon = SpringUtils.getMapService().heroIcon(sex, xiangXin);
        bossParam.setIcon(icon);

        /**weaponIcon*/
        short weaponIcon = (short) data.getAs(String.valueOf(xiangXin), NutMap.class).getInt(String.valueOf(level));
        bossParam.setWeaponIcon(weaponIcon);
        /**套装icon*/
        int suitId = SpringUtils.getBean(SuitService.class).getSuitId(level, sex, xiangXin);
        bossParam.setSuitIcon(suitId);
        if (level >= 70) {
            /**套装光效*/
            int lightId = getRandomLightId();
            bossParam.setSuitLightEffect(lightId);
        }

        return bossParam;
    }

    /**
     * 在战斗胜利后移除星官
     */
    private void clearXingGuanAfterFightWin(NPC npc) {
        clearXingGuan(npc);

//        long delay = XINGGUAN_NEXT_SHOW * TimeUtil.ONE_MINUTE;
//        SchedulerManager.getInstance().schedule(() -> xingGuanWillCome(npc.getXing()), delay);
    }

    /**
     * 移除星官
     */
    private void clearXingGuan(NPC npc) {
        if (npc == null) {
            return;
        }

        DataCache.XING_NPCS.remove(npc.getId());
        Set<Integer> set = DataCache.XING_MAP_NPC.get(npc.getMapId());
        if (set != null) {
            set.remove(npc.getId());
        }
        removeUsedPosition(npc.getMapId(), npc.getX(), npc.getY());

        bossService.broadcastNpcHide(null, npc);
    }

    /**
     * 给奖励
     */
    public void giveReward(Role role, FightEndEvent fightEndEvent, NPC bossNpc) {
        /**判断是否给奖励*/
        if (isGiveReward(role, bossNpc) == false) {
            MessagePusher.pushMessage(role,new RespNotifyMiscEx("高于星官29级以上,无法获得奖励！！！"));
            return;
        }
        fightService.sendBossBasicsRewardNotXing(role,fightEndEvent);
        fightService.sendBossExtReward(role,fightEndEvent);
        if (bossNpc.getName().contains("天")){
            SpringUtils.getActivityService().addFinishCount(role, ActivityType.XING_GUAN_tian, 1);
        }else {
            SpringUtils.getActivityService().addFinishCount(role, ActivityType.XING_GUAN_di, 1);
        }
        int index = ThreadLocalRandom.current().nextInt(10);
        if(index<=4){
            SpringUtils.getBean(BianYiXingGuanHandler.class).flushBianYiXingGuan(bossNpc);
        }

    }

    /**
     * 是否给奖励
     */
    private boolean isGiveReward(Role role, NPC bossNpc) {
        if (bossNpc == null) {
            return false;
        }
        if (role.getLevel() > bossNpc.getLevel() + REWARD_MAX_MORE_LEVEL) {
            return false;
        }

        return true;
    }

    @Override
    protected void clearNpcTimeOut(NPC npc) {
        clearXingGuanTimeOut(npc);
    }

    @Override
    public void doFightFail(Role role, FightEndEvent fightEndEvent) {
        super.doFightFail(role, fightEndEvent);
        teamService.memberHandleThreadLocal(role, memberRole -> SpringUtils.getRoleService().punishFightDead(memberRole));

        /**回到出生点*/
        SpringUtils.getRoleService().goBackBorn(role);
    }

    @Override
    public void doFightWinForSingle(Role role, FightEndEvent fightEndEvent, NPC bossNpc) {
        if (role.getLastDead() == 0){
            teamService.memberHandleThreadLocal(role, memberRole -> SpringUtils.getRoleService().punishFightDead(memberRole));
        }else {
            super.doFightWinForSingle(role, fightEndEvent, bossNpc);
        }
    }
}
